//
//  ZoomingScrollView.m
//  SimPhotoBrowser

#import "SimZoomImagelView.h"
#import "SimPhotoBrowser.h"
#import "SimPhotoModel.h"
#import "SimLoading.h"
#import "DACircularProgressView.h"
#import "UIViewController+SimAddition.h"
#import "UIView+SimAdditions.h"
#import "SimLoading.h"
#import <SDWebImage/UIImageView+WebCache.h>

@interface SimZoomImagelView ()  <UIScrollViewDelegate>{
    
    __weak SimPhotoBrowser *_photoBrowser;
    DACircularProgressView *_loadingIndicator;
    
    UIScrollView *_scrollView;
    UIImageView *_loadingError;
    UIImageView *_overlayImageView;
}


@end

@implementation SimZoomImagelView

- (id)initWithPhotoBrowser:(SimPhotoBrowser *)browser {
    if ((self = [super init])) {
        // Setup
        _index = NSUIntegerMax;
        _photoBrowser = browser;
        
        // Listen progress notifications
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(beginLoadImageNotification:)
                                                     name:kSimPhotoModelImageLoadBeginNoti
                                                   object:nil];

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(setProgressFromNotification:)
                                                     name:kSimPhotoModelImageLoadProgressNoti
                                                   object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(finishLoadImageNotification:)
                                                     name:kSimPhotoModelImageLoadFinishNoti
                                                   object:nil];

        
        _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
        _scrollView.backgroundColor = [UIColor blackColor];
		_scrollView.delegate = self;
		_scrollView.showsHorizontalScrollIndicator = NO;
		_scrollView.showsVerticalScrollIndicator = NO;
        [_scrollView setBouncesZoom:YES];
		_scrollView.decelerationRate = UIScrollViewDecelerationRateFast;
		_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [_scrollView setClipsToBounds:NO];
        [self addSubview:_scrollView];
        
        _imageView = [[UIImageView alloc] initWithFrame:self.bounds];
        _imageView.userInteractionEnabled = YES;
        [_imageView setContentMode:UIViewContentModeScaleAspectFit];
        [_imageView setClipsToBounds:NO];
        [_scrollView addSubview:_imageView];
        
        [self.imageView addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil];
        [self loadTouchGestureRecognizers];

    }
    return self;
}

- (void)dealloc {
    [self.imageView removeObserver:self forKeyPath:@"image"];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (object == self.imageView && [keyPath isEqualToString:@"image"]){
        [self setAlpha:1];
        [self updateImage:self.imageView.image];

    }
}

- (void)setZoomScrollViewBgColor:(UIColor *)color
{
    _scrollView.backgroundColor = color ? :  [UIColor blackColor];
}

- (void)updateImage:(UIImage *)image
{
    if (image) {
        [self setAlpha:1];
        if (self.imageView.image != image) {
            if (self.imageView.image != nil) {
                [self.imageView setAlpha:0];
            }
            [UIView animateWithDuration:0.1
                                  delay:0
                                options:UIViewAnimationOptionCurveEaseIn
                             animations:^{
                                 [self.imageView setAlpha:1];
                             }completion:nil];
            
            [self.imageView setImage:image];
            [self setMaxMinZoomScalesForCurrentBounds];
        }
        else{
            [self.imageView setAlpha:1];
        }
    }
    else{
        [self setMaxMinZoomScalesForCurrentBounds];
    }

}

- (void)loadTouchGestureRecognizers
{
    UITapGestureRecognizer *singleTapRecognizer = [[UITapGestureRecognizer alloc]
                                                   initWithTarget:self action:@selector(didRecognizeSingleTap:)];
    [singleTapRecognizer setNumberOfTapsRequired:1];
    [_scrollView addGestureRecognizer:singleTapRecognizer];
    
    
    UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc]
                                                initWithTarget:self
                                                action:@selector(didRecognizeDoubleTap:)];
    [doubleTapGesture setNumberOfTapsRequired:2];
    [_scrollView addGestureRecognizer:doubleTapGesture];
    
    UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc]
                                                      initWithTarget:self
                                                      action:@selector(didRecognizeLongPress:)];
    [_scrollView addGestureRecognizer:longPressGesture];
    
    [singleTapRecognizer requireGestureRecognizerToFail:doubleTapGesture];
}

#pragma mark - Event Hooks

- (void)didRecognizeSingleTap:(id)sender
{
    if (_singlTap) {
        _singlTap(self, sender);
    }
}

- (void)didRecognizeDoubleTap:(id)sender
{
    UITapGestureRecognizer *tap = sender;
    // Zoom
    if (_scrollView.zoomScale != _scrollView.minimumZoomScale) {
        [_scrollView setZoomScale:_scrollView.minimumZoomScale animated:YES];
    } else {
        // Zoom in to twice the size
        CGFloat newZoomScale = ((_scrollView.maximumZoomScale + _scrollView.minimumZoomScale) / 2);
        CGFloat xsize = _scrollView.bounds.size.width / newZoomScale;
        CGFloat ysize = _scrollView.bounds.size.height / newZoomScale;
        CGPoint touchPoint = [tap locationInView:_imageView];
        [_scrollView zoomToRect:CGRectMake(touchPoint.x - xsize/2, touchPoint.y - ysize/2, xsize, ysize) animated:YES];
    }
    
    
    if (_doubleTap) {
        _doubleTap(self, sender);
    }
}

- (void)didRecognizeLongPress:(id)sender
{
    UILongPressGestureRecognizer *longPressGesture = sender;
    if (longPressGesture.state == UIGestureRecognizerStateBegan){
        if (_longPress) {
            _longPress(self, sender);
        }
    }    
}


#pragma mark - Image
- (void)setPhoto:(SimPhotoModel *)photo
{
    if (_photo && photo != _photo) {
        [_photo cancelImageLoad];
    }
    
    _photo = photo;
    [self beginDisplayImage];
}


- (void)beginDisplayImage
{
    [self showLoadingIndicator:NO];
    [self showImageFailure:NO];
    
    UIImage *image = nil;
    if (_photo && [_photo isKindOfClass:[SimPhotoModel class]]) {
        image = _photo.loadedImage;
        if (image == nil) {
            image = _photo.thumbImage;
            [self updateImage:image];
            [_photo tryLoadImage];
        }
        else{
            [self updateImage:image];
        }
        
        if (_photo.overlayURL) {
            if (_overlayImageView == nil) {
                _overlayImageView = [[UIImageView alloc] initWithFrame:_imageView.bounds];
                _overlayImageView.autoresizesSubviews = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
                [_overlayImageView setContentMode:_imageView.contentMode];
                [_overlayImageView sd_setImageWithURL:_photo.overlayURL];
                [_imageView addSubview:_overlayImageView];
            }
            else{
                _overlayImageView.frame = _imageView.bounds;
            }
        }
        else{
            if (_overlayImageView) {
                [_overlayImageView removeFromSuperview];
                _overlayImageView = nil;
            }
        }
        [self setNeedsLayout];
    }
    else{
        [self showImageFailure:YES];
    }
}

- (void)showLoadingIndicator:(BOOL)show
{
    if (show) {
        [self showImageFailure:NO];
        
        if (!_loadingIndicator) {
            _loadingIndicator = [[DACircularProgressView alloc] initWithFrame:CGRectMake(140.0f, 30.0f, 40.0f, 40.0f)];
            [self addSubview:_loadingIndicator];
            _loadingIndicator.userInteractionEnabled = NO;
            
        }
        _loadingIndicator.center = CGPointMake(self.width/2, self.height/2);
    }
    else{
        if (_loadingIndicator) {
            [_loadingIndicator removeFromSuperview];
            _loadingIndicator = nil;
        }
    }
 }

- (void)showImageFailure:(BOOL)show
{
    if (show) {
        [self showLoadingIndicator:NO];
        [self updateImage:nil];

        if (self.imageView.image == nil) {
            if (!_loadingError) {
                _loadingError = UIImageViewNamed(@"icon_imageLoadError");
                [self addSubview:_loadingError];
            }
            _loadingError.center = CGPointMake(self.width/2, self.height/2);
        }
    }
    else{
        if (_loadingError) {
            [_loadingError removeFromSuperview];
            _loadingError = nil;
        }
    }
}


#pragma mark - Loading Progress

- (void)beginLoadImageNotification:(NSNotification *)notification
{
    if (notification.object == self.photo) {
        [self showLoadingIndicator:YES];
    }
}

- (void)finishLoadImageNotification:(NSNotification *)notification
{
    if (notification.object == self.photo) {
        if (self.photo.loadedImage == nil) {
            [self showImageFailure:YES];
        }
        else{
            [self beginDisplayImage];
        }
    }
}

- (void)setProgressFromNotification:(NSNotification *)notification
{
    NSDictionary *dict = [notification object];
    SimPhotoModel * photoWithProgress = [dict objectForKey:@"photo"];
    if (photoWithProgress == self.photo) {
//        _loadingIndicator.progress = Range(progress, 0.0f, 1.0f);
    }
}

- (void)setMaxMinZoomScalesForCurrentBounds
{
    [self resetZoomScale];
    [self resetImageViewFrame];
	[self setNeedsLayout];
}

- (void)resetImageViewFrame
{
    CGRect rct = _imageView.frame;
    rct.size = CGSizeMake(_scrollView.zoomScale*_imageView.image.size.width, _scrollView.zoomScale*_imageView.image.size.height);
    _imageView.frame = rct;

}

- (void)resetZoomScale
{
    if (_imageView.image != nil) {
        CGFloat Rw = _scrollView.frame.size.width/_imageView.image.size.width;
        CGFloat Rh = _scrollView.frame.size.height/_imageView.image.size.height;
        CGFloat ratio = MIN(Rw, Rh);
        _scrollView.minimumZoomScale = ratio;
        _scrollView.maximumZoomScale = DEVICE_IS_IPAD ? 4 : 3;
    }
    else{
        _scrollView.minimumZoomScale = 0.0;
        _scrollView.maximumZoomScale = 0.0;
    }
    
    _scrollView.contentSize = _imageView.frame.size;
    [_scrollView setZoomScale:_scrollView.minimumZoomScale animated:NO];
}


#pragma mark - Layout

- (void)layoutSubviews
{
    [super layoutSubviews];
    if (_loadingError){
        _loadingError.center = CGPointMake(self.width/2, self.height/2);
    }
	
    CGFloat left = (_imageView.width < _scrollView.width) ? floorf((_scrollView.width - _imageView.width) / 2.0) : 0;
    CGFloat top = (_imageView.height < _scrollView.height) ? floorf((_scrollView.height - _imageView.height) / 2.0) : 0;
    if (_imageView.left != left || _imageView.top != top) {
        _imageView.origin = CGPointMake(left, top);
    }
}

#pragma mark - UIScrollViewDelegate
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
	return _imageView;
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
}

- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
{
    _scrollView.scrollEnabled = YES;
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
    [self setNeedsLayout];
    [self layoutIfNeeded];
}


@end
